package gecko.main;

import com.moandjiezana.toml.Toml;
import gecko.GeckoEngine;
import gecko.lang.ShutdownHook;
import gecko.x.ClassX;
import gecko.x.CollectionX;
import gecko.x.MergeX;

import java.io.File;
import java.util.*;
import java.util.concurrent.CountDownLatch;

/**
 * @author 陈永佳 (yoojiachen@gmail.com)
 * @version 0.0.1
 */
public class GeckoApplication {

    private static final Set<String> BUILD_IN = CollectionX.setOf(
            "globals.toml"
    );

    private static final GeckoEngine GECKO_ENGINE = new GeckoEngine();

    private static final CountDownLatch SIGNAL = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {
        // shutdown signal
        ShutdownHook.add(() -> {
            if (SIGNAL.getCount() < 1) {
                SIGNAL.countDown();
            }
        });
        final String defaultConfigFile = System.getProperty("gecko.default.config", "config.toml");
        try {
            // startup
            GECKO_ENGINE.init(loadConfig(CollectionX.setOf(defaultConfigFile, "config.d")));
            GECKO_ENGINE.start();
            // wait signal
            SIGNAL.await();
        } finally {
            GECKO_ENGINE.shutdown();
        }
    }

    private static Map<String, Object> loadConfig(Set<String> paths) {
        final Toml toml = new Toml();
        // 内置配置
        final Map<String, Object> buildIn = BUILD_IN.stream()
                .map(r -> toml.read(Objects.requireNonNull(ClassX.CLASS_LOADER.getResourceAsStream(r))))
                .filter(m -> null != m && !m.isEmpty())
                .map(Toml::toMap)
                .reduce(new HashMap<>(), MergeX::merge);

        // 外部配置
        return paths.stream()
                .map(File::new)
                .filter(File::exists)
                .flatMap(f -> {
                    if (f.isDirectory()) {
                        return Arrays.stream(Objects.requireNonNull(f.listFiles()));
                    } else {
                        return CollectionX.setOf(f).stream();
                    }
                }).map(f -> toml.read(f).toMap())
                .reduce(buildIn, MergeX::merge);
    }
}
